/**
 * @class   wosh::ThreadManager
 * @brief   CoreModule designed for diagnostic and debug purposes,
 *          it collects and keep track of application's threads transparently.
 *          Often it is able to detect crashes.
 *
 *
 * \image html diagrams/ThreadManager.png "wosh::ThreadManager UML diagram"
 *
 * \par Kernel Initialization [\c onKernelInitializing()]:
 * \msc
ThreadManager,Kernel;
ThreadManager->ThreadManager [label="WoshModule::onKernelInitializing()", URL="\ref wosh::WoshModule::onKernelInitializing()"];
|||;
--- [ label=" IF ThreadMonitor "];
ThreadManager<=ThreadManager [label="start ThreadManagerMonitor thread", URL="\ref wosh::ThreadManagerMonitor"];
--- [ label=" ENDIF ThreadMonitor "];
 * \endmsc
 *
 * \see     \ref page_core_threads
 * \see     wosh::Thread
 * \ingroup CoreModules
 ****************************************************************************
 * @version 0.8.499 $Id: ThreadManager.h 2576 2010-05-27 10:21:27Z alex $
 * @author  Alessandro Polo
 ****************************************************************************/
/*! \page page_core
 * \htmlonly <hr/> \endhtmlonly
 * \section page_core_threads Threading
 *
 * wosh::ThreadManager is a core-module provided for debugging and monitoring
 * internal threads of the application.
 *
 * The wosh::Thread class provides an high-level abstraction layer for implementing
 * threads, moreover it raises events and cooperates transparently with ThreadManager.
 *
 * wosh::Thread base class transparently (un)registers itself and notifies state-changes.
 *
 * Current implementation is based (only) on \c QT4 classes (QThread).
 * An implementation on \c pthreads is under planning.
 *
 * The wosh::Thread implementation provides usual start/stop/quit/wait calls,
 * synchronous and asynchronous, getters for current thread-state.
 * Each thread is associated with an (internal) unique identifier (numeric) and
 * an optional (string) name.
 *
 * \see wosh::Thread for sample implementation of a generic thread. 
 *
 * Thread Manager provides also a monitoring utility which periodically evaluates
 * if a thread has been crashed/dead-locked (not-responding).
 * wosh::ThreadMonitor is enabled by default and required in order to detect crashed threads.
 * Termination detection is probabilistic and depend on implementation (some components may not support this feature),
 * it is based on iterative timestamping and timeout evaluation,
 * the crash probability is estimated agaist last alive-timestamp and projected timeout (custom value for each thread).
 *
 * High-rate tasks may use wosh::ThreadPool to distribute work in a predefined set of threads, eventually
 * linked to local methods. wosh::BusMT and wosh::services::TaskManagerBundle are based on that component.
 *
 * \see wosh::ThreadManager
 * \see wosh::Thread
 *
 ****************************************************************************/
/* Copyright (c) 2007-2010, WOSH - Wide Open Smart Home 
 * by Alessandro Polo - OpenSmartHome.com
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the OpenSmartHome.com WOSH nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY Alessandro Polo ''AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL Alessandro Polo BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ThreadS;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ****************************************************************************/

#ifndef __WOSH_Core_ThreadManager_H__
 #define __WOSH_Core_ThreadManager_H__

 #include <woshDefs.h>
 #include <core/WoshModule.h>
 #include <core/Thread.h>


namespace wosh {

 #define _ThreadManager_NAME				"ThreadManager"
 #define _ThreadManager_URI					":Threads"

 #define _ThreadManager_KEY_Count			"Count"
 #define _ThreadManager_KEY_ThreadMonitor	"ThreadMonitor"

 #define _ThreadManager_METHOD_start		"start"
 #define _ThreadManager_METHOD_stop			"stop"
 #define _ThreadManager_METHOD_terminate	"terminate"

 #define _ThreadManager_ERROR_stop_failure	201
 #define _ThreadManager_ERROR_dead_thread	1001


class ThreadManagerMonitor;
class WoshKernel;

class ThreadManager : public WoshModule
 {
	WOSH_MODULE(wosh::ThreadManager)

	typedef ListT<wosh::Thread*> tThreadList;


	protected:
		/**
		 * @brief  Default constructor. Call base constructor and initialize some properties and hosted methods.
		 * @param parent [in] WoshKernel singleton, passed to WoshModule constructor
		 * @note   Called by WoshKernel or by static getter (meyer singleton)
		 */
		ThreadManager( const WoshKernel* parent = NULL );

		/**
		 * @brief  Call base class implementation and eventually start ThreadMonitor.
		 * @return result of WoshModule::onKernelInitializing()
		 */
		WRESULT onKernelInitializing();

		/**
		 * @brief  Stop all (registered) running threads. Reentrant.
		 * @param  timeout [in] timeout in milliseconds, 0 means asynch call; default is no timeout
		 * @return WRET_OK if no threads are running or all have been successfully stopped, sumOf[WRESULT of quitThread()] else
		 * @note   timeout is forwarded: it is not considered as the global timeout, but as timeout for-each thread-quit)
		 */
		WRESULT stopThreads( unsigned long timeout = LIMIT_ULONG_MAX );

		friend class wosh::WoshKernel;

	public:
		/**
		 * @brief  Destructor. When ThreadMonitor is running it is stopped (synch, no timeout);
		 *         if any thread is still running, it is stopped (synch, 30 second timeout for each thread)
		 * @see    ThreadManager::monitor
		 */
		virtual ~ThreadManager();

//@}
/** @name Public methods
 * @{
 ******************************************************************************/
	public:
		/**
		 * @brief  Get the number of threads. Reentrant.
		 * @return the number of registered threads
		 */
		int count() const					{ return this->threads.size(); }
		/**
		 * @brief  Get the number of running threads. Reentrant.
		 * @return the number of registered threads that are running (Thread::STATE_RUNNING)
		 */
		int countRunning() const;
		/**
		 * @brief  Get the number of non-running threads. Reentrant.
		 * @return the number of registered threads that are NOT running
		 */
		int countStopped() const			{ return count() - countRunning(); }

//@}
/** @name IPropertiesProviderListener interface
 * @{
 ******************************************************************************/
 	protected:
		bool updatingProperty( bool& do_update, const Variant& value_proposed, Property& property_current, const PropertiesProvider* source );
		friend class wosh::PropertiesProvider;
//@}
/** @name Thread Events (create/start/stop/destroy notification)
 * @{
 ******************************************************************************/
	protected:
		/**
		 * @brief  Raise (internal) events from (base) Thread instances.
		 * @param  thread_event [in] the event type
		 * @param  thread [in] pointer to the source of the event
		 * @note   called on: constructor, thread-state change, destructor
		 */
		static inline void push_event( Thread::THREAD_STATE thread_event, Thread* thread ) {
			ThreadManager::getInstance().thread_event( thread_event, thread );
		 }
		friend class wosh::Thread;
//@}
/** @name Internal Mehods and Thread-Events management
 * @{
 ******************************************************************************/
	private:
		/**
		 * @brief  Access the ThreadManager singleton. Meyer Pattern.
		 *         Static reference is allocated on first use, destroyed by WoshKernel
		 * @return reference to ThreadManager singleton
		 * @note   this is designed using meyer singleton because some threads may be allocated
		 *         very early (because of inheritance), so basically the kernel will acquire
		 *         (on-creation) the object, and will destroy it in destructor.
		 *         (later, compiler will destroy only the static pointer)
		 */
		static ThreadManager& getInstance();

	private:
		/**
		 * @brief  Manage Thread events, pushed internally.
		 *         Thread is registered on Thread::STATE_CREATED, unregistered on Thread::STATE_DESTROYED,
		 *         other events are state-changes and are just logged.
		 * @param  thread_event [in] the event type
		 * @param  thread [in] pointer to the source of the event
		 * @see    push_event()
		 */
		void thread_event( Thread::THREAD_STATE thread_event, Thread* thread );

		/**
		 * @brief  Register (add) a new thread. Only reference is stored, no copy operations. NOT reentrant.
		 * @param  thread [in] pointer of the thread to be added
		 * @return WRET_ERR_PARAM when thread is NULL or already registered (pointer lookup). WRET_OK else
		 * @note   this call is automatically raised by wosh::Thread constructor.
		 * @see    thread_event()
		 */
		WRESULT registerThread_( Thread* thread );
		/**
		 * @brief  UnRegister (remove) a new thread. Only entry is removed, no operation on thread. NOT reentrant.
		 * @param  thread [in] pointer of the thread to be removed
		 * @return WRET_ERR_PARAM when thread is NULL or not-found (pointer lookup). WRET_OK else
		 * @note   this call is automatically raised by wosh::Thread destructor.
		 * @see    thread_event()
		 */
		WRESULT unRegisterThread_( Thread* thread );

		/**
		 * @brief  Count running threads. NOT reentrant.
		 * @return number of registered threads in Thread::STATE_RUNNING state
		 */
		int countRunning_() const;
//@}
	private:
		Response* mmDoStartThread( const Request* request );
		Response* mmDoStopThread( const Request* request );
		Response* mmDoTerminateThread( const Request* request );

	private:
		tThreadList threads;			///< threads' collection
		ThreadManagerMonitor* monitor;	///< (optional) monitor for crashed threads
		friend class wosh::ThreadManagerMonitor;


}; // class def

}; // namespace wosh

#endif //__WOSH_Core_ThreadManager_H__
